//
// Created by pzw on 24-3-1.
//

#ifndef QTTEST_HASHSET_H
#define QTTEST_HASHSET_H

#include <unordered_set>
#include <functional>
#include <vector>
#include <iostream>

template<typename T>
class HashSetIterator;

template<
        typename Value,
        typename Hash = std::hash<Value>,
        typename Pred = std::equal_to<Value>,
        typename Alloc = std::allocator<Value>
>
class HashSet {
private:
    std::unordered_set<Value, Hash, Pred, Alloc> *set;

public:
    explicit HashSet(std::unordered_set<Value, Hash, Pred, Alloc> *set);
    ~HashSet();

public:
    std::unordered_set<Value, Hash, Pred, Alloc> *cset();
    bool add(Value e);
    void clear();
    HashSet<Value, Hash, Pred, Alloc> clone();
    bool contains(Value o);
    bool isEmpty();
    HashSetIterator<Value> iterator();
    bool remove(Value o);
    size_t size();
    std::vector<Value> toArray();
    template<typename T>
    std::vector<T> toArray2(std::vector<T> &a);
    bool containsAll(const std::unordered_set<Value, Hash, Pred, Alloc> &c);
    bool addAll(const std::unordered_set<Value, Hash, Pred, Alloc> &c);
    bool removeAll(const std::unordered_set<Value, Hash, Pred, Alloc> &c);
    bool retainAll(const std::unordered_set<Value, Hash, Pred, Alloc> &c);
    bool equals(const HashSet<Value, Hash, Pred, Alloc> &o);
    int hashCode();
    void forEach(std::function<void(const Value &)> action);
    std::string toString();

};

/**
 * 迭代器
 *
 * @tparam T - 模板参数
 */
template<typename T>
class HashSetIterator {
private:
    typename std::unordered_set<T>::iterator it;
    typename std::unordered_set<T> &setRef;

public:
    explicit HashSetIterator(typename std::unordered_set<T> &set) : setRef(set) {
        it = setRef.begin();
    }

    /**
     * java 的 hasNext函数
     *
     * @return it is end?
     */
    bool hasNext() {
        return it != setRef.end();
    }

    /**
     * 获取当前值，并且迭代器自增
     *
     * @return 当前值
     */
    T next() {
        if (it == setRef.end()) {
            // Handle error or exception
            throw std::out_of_range("Iterator out of range");
        }
        T value = *it;
        ++it;
        return value;
    }

    /**
     * 移出当前值，并且迭代器自减
     *
     * @return void
     */
    void remove() {
        if (it != setRef.begin()) { // 确保不是在容器的开始位置尝试删除
            // 删除元素，并将迭代器移动到下一个有效元素
            const typename std::unordered_set<T>::iterator itr = std::prev(it);
            it = setRef.erase(itr);
        } else {
            std::cout << "Cannot remove before calling next" << std::endl;
        }
    }

};

int HashSet_main();

#endif //QTTEST_HASHSET_H
